package myjava.q_encode;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * @Classname : Encode
 * @Description : 编码格式
 * @Author : cty
 * @Date 2023/4/9 23:55
 */


public class Encode {
    public static void main(String[] args) throws UnsupportedEncodingException {
        /**
         * 编码格式和解码格式不同导致乱码
         */
        String s = "我爱中国";
        System.out.println("字符序列：" + s);
        byte[] GBK_bytes = s.getBytes(Charset.forName("GBK"));
        System.out.println("GBK编码：" + bytesToHexFormat(GBK_bytes));
        System.out.println("GBK编码，GBK解码：" + new String(GBK_bytes, "GBK"));
        System.out.println("GBK编码，GB2312解码：" + new String(GBK_bytes, "GB2312"));
        System.out.println("GBK编码，GB18030解码：" + new String(GBK_bytes, "GB18030"));
        System.out.println("GBK编码，UTF-8解码：" + new String(GBK_bytes, "UTF-8"));
        System.out.println("--------------------------------------------------------------------------");

        /**
         * 常见乱码：Unicode中使用"�"来表示无法正常显示的字符或表情，且"��"的UTF-8编码与"锟斤拷"的GBK编码相同
         * 乱码过程：GBK编码——>UTF-8解码（出现"��"）——>UTF-8编码——>GBK解码（出现"锟斤拷"）
         */
        String s1 = "��";
        System.out.println("字符序列：" + s1);
        byte[] UTF8_bytes = s1.getBytes(StandardCharsets.UTF_8);
        System.out.println("UTF_8编码：" + bytesToHex(UTF8_bytes));
        System.out.println("UTF-8编码，UTF-8解码：" + new String(UTF8_bytes, "UTF-8"));
        System.out.println("UTF-8编码，GBK解码：" + new String(UTF8_bytes, "GBK"));
        System.out.println("--------------------------------------------------------------------------");

        String s2 = "锟斤拷";
        System.out.println("字符序列：" + s2);
        byte[] GBK_bytes2 = s2.getBytes(Charset.forName("GBK"));
        System.out.println("GBK编码：" + bytesToHex(GBK_bytes2));
        System.out.println("GBK编码，GBK解码：" + new String(GBK_bytes2, "GBK"));
        System.out.println("GBK编码，UTF-8解码：" + new String(GBK_bytes2, "UTF-8"));
        System.out.println("--------------------------------------------------------------------------");

        // 常见乱码：Debug模式下Visual C会把栈中分配内存初始化为0xcc，而0xcccc是GBK中汉字"烫"的编码
        // 模拟一个字节的初始化的栈内存块
        byte byte1 = Integer.valueOf("cc", 16).byteValue();
        byte[] stack = new byte[8];
        for (int i = 0; i < stack.length; i++) stack[i] = byte1;
        System.out.println("栈内存初始化序列：" + bytesToHex(stack));
        System.out.println("GBK解码：" + new String(stack, "GBK"));
        System.out.println("--------------------------------------------------------------------------");

        // 常见乱码：Debug模式下Visual C会把堆中分配内存初始化为0xcd，而0xcdcd是GBK中汉字"屯"的编码
        // 模拟一个字节的初始化的堆内存块
        byte byte2 = Integer.valueOf("cd", 16).byteValue();
        byte[] heap = new byte[8];
        for (int i = 0; i < heap.length; i++) heap[i] = byte2;
        System.out.println("堆内存初始化序列：" + bytesToHex(heap));
        System.out.println("GBK解码：" + new String(heap, "GBK"));
    }

    public static String bytesToHexFormat(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            if (i % 2 == 0) {
                if (i != 0) {
                    sb.append(' ');
                }
                sb.append("0x");
            }
            sb.append(String.format("%02X", bytes[i]));
        }
        return sb.toString();
    }

    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
}

/** 20230409
 * 字符序列：我爱中国
 * GBK编码：0xCED2 0xB0AE 0xD6D0 0xB9FA
 * GBK编码，GBK解码：我爱中国
 * GBK编码，GB2312解码：我爱中国
 * GBK编码，GB18030解码：我爱中国
 * GBK编码，UTF-8解码：�Ұ��й�
 * --------------------------------------------------------------------------
 * 字符序列：��
 * UTF_8编码：EFBFBDEFBFBD
 * UTF-8编码，UTF-8解码：��
 * UTF-8编码，GBK解码：锟斤拷
 * --------------------------------------------------------------------------
 * 字符序列：锟斤拷
 * GBK编码：EFBFBDEFBFBD
 * GBK编码，GBK解码：锟斤拷
 * GBK编码，UTF-8解码：��
 * --------------------------------------------------------------------------
 * 栈内存初始化序列：CCCCCCCCCCCCCCCC
 * GBK解码：烫烫烫烫
 * --------------------------------------------------------------------------
 * 堆内存初始化序列：CDCDCDCDCDCDCDCD
 * GBK解码：屯屯屯屯
 */
